"""
Contains track types

"""
import functools
from atlas import web
from atlas.plotting import chart
from atlas.plotting.const import *

def safe_max( data, default=1 ):
    """
    Safe max, that can handle an empty list
    >>> safe_max( [1,2,3 ] )
    3
    >>> safe_max( [] )
    1
    """
    try:
        return max(data)
    except ValueError:
        return default

def multi_track( data, ycs, options ):
    """
    Creates a multi line track
    """
    
    # draw the seqments
    simple = chart.TrackChart( options=options )
    for row, yc in zip(data, ycs):
        simple.draw_segments( row, color=options.fgColor, yc=yc, lw=options.lw )
        simple.base_line( y=[yc, yc] )
    return simple

def simple_track( data, options ):
    """
    Creates a line track
    """
    
    # remove overlapping labels
    if options.show_labels:
        data = remove_overlapping( data=data, width=options.w, xscale=options.xscale, fontsize=options.fontSize)

    # draw the seqments
    simple = chart.TrackChart( options=options )
    simple.draw_segments( data, color=options.fgColor )
    simple.base_line( y=[0, 0] )
    return simple



def split_tracks( features, options, colors=[BLUE, RED], track_type='line', split=False ):
    """
    Creates vector tracks. Will draw them with two colors by strand.
    """
    
    # need to split by by strand
    pfeats = filter( lambda x: x.strand=='+', features )
    mfeats = filter( lambda x: x.strand=='-', features )

    # make them into data
    pdata  = web.feature2data( pfeats )
    mdata  = web.feature2data( mfeats )
    
    # remove overlapping labels
    if options.show_labels:
        fix_overlap = functools.partial( remove_overlapping, 
            width=options.w, xscale=options.xscale, 
            fontsize=options.fontSize
        )
        pdata = fix_overlap( data=pdata )
        mdata = fix_overlap( data=mdata )
    
    # split into two
    if split:
        options.h, yc, lpos = 80, 2, 30
    else:
        options.h, yc, lpos = 60, 0, 0

    vtrack = chart.TrackChart( options=options )
    
    if track_type == 'vector':
        vtrack.draw_vectors( data=pdata, color=colors[0], yc=yc )
        vtrack.draw_vectors( data=mdata, color=colors[1], yc=-yc, lpos=lpos  )
    else:
        vtrack.draw_segments( data=pdata, color=colors[0], yc=yc )
        vtrack.draw_segments( data=mdata, color=colors[1], yc=-yc, lpos=lpos  )

    vtrack.base_line( y=[ yc, yc ] )
    vtrack.base_line( y=[-yc, -yc] )
    return vtrack


def fitted_data( line_x, line_y, bars_x, bars_y, options ):
    """
    Creates a plot that contains a bars and a line superimposed
    """
    bar = chart.XYChart( options=options )
    bar.base_line( y=[0, 0] )
    bar.draw_line( x=line_x, y=line_y, yaxis2=True, color=options.fgColor, lw=options.lw ) 
    bar.draw_bars( x=bars_x, y=bars_y, color=options.barColor )    
    return bar 

def mirrored_fitted_data( line_upx, line_upy, bars_upx, bars_upy, 
    line_dwx, line_dwy, bars_dwx, bars_dwy, options ):
    """
    Creates a plot that contains a bars and a line superimposed and mirrored
    around the 0 line. There is a separate bargraph and line graph for the 
    upper and lower split
    """

    # detect maximal values to scale both sides of the mirrored 
    # axis  indentically and keep the zero line at center 
    barmax = max( ( safe_max(bars_upy), safe_max(bars_dwy) ) )
    fitmax = max( ( safe_max(line_upy), safe_max(line_dwy) ) )

    options.yscale  = [ -barmax, barmax ]
    options.yscale2 = [ -fitmax, fitmax ]

    bar = chart.XYChart( options=options )
    bar.base_line( y=[0, 0] )

    # upper plot 
    bar.draw_line(x=line_upx, y=line_upy, yaxis2=True, color=BLUE, lw=options.lw )
    bar.draw_bars(x=bars_upx, y=bars_upy, color=BLUE)

    # invert values for the lower plot
    bars_dwy = [ -y for y in bars_dwy ]    
    line_dwy = [ -y for y in line_dwy ]    
    bar.draw_line(x=line_dwx, y=line_dwy, yaxis2=True, color=RED, lw=options.lw )
    bar.draw_bars(x=bars_dwx, y=bars_dwy, color=RED)   
    
    return bar 


def test( verbose=0 ):
    "Performs module level testing"
    import doctest
    doctest.testmod( optionflags=doctest.ELLIPSIS + doctest.NORMALIZE_WHITESPACE, verbose=verbose )

if __name__ == "__main__":
    test()
    
    #opt = chart_options( xscale=[0,10], fgColor=PURPLE,XAxisOnTop=1, bpad=0, edgeColor=GREY, ylabel='Reads', ylabel2='Fit', w=800, lw=2 )
    #x = y = range(10)
    #bar = fitted_data( linex=x, liney=y, barx=x, bary=y, options=opt)
    #bar.show()